#!/usr/bin/ruby
# -*- ruby -*-
#
# http://www.reddit.com/r/dailyprogrammer/comments/101mi5/9172012_challenge_99_intermediate_unemployment/

require 'optparse'
require 'rexml/document'

# Standard app options
options = {
  :svg => File.basename($0).gsub(/\.rb$/, '.svg'),
  :csv => File.basename($0).gsub(/\.rb$/, '.csv'),
  :day => '1980-01-01',
  :col => File.basename($0).gsub(/\.rb$/, '.col'),
  :out => 'processed.svg',
}

OptionParser.new do |o|
  o.on('--svg=SVG', String) { |options[:svg]| }
  o.on('--csv=CSV', String) { |optoins[:csv]| }
  o.on('--day=CSV', String) { |options[:day]| }
  o.on('--col=COL', String) { |options[:col]| }
  o.on('--out=OUT', String) { |options[:out]| }
end.parse!

# Grab the data out of our file
header = nil
data = nil

File.open(options[:csv]) do |csv_fh|
  lines = csv_fh.readlines
  header = lines.first

  lines.each do |line|
    data = line if line =~ /^#{options[:day]},/

    break if data
  end
end

# Built up a mapping from state to unemployment date
header = header.strip.split(',')
data   = data.strip.split(',').map { |d| d.to_f }

header.shift
data.shift

joined = header.zip(data)

# Pull in the color scale
colors = []
File.open(options[:col]) do |col_fh|
  colors = col_fh.readlines.map { |l| l.strip }
end

# Assign ranges for the color scale
max  = data.max.ceil
min  = data.min.floor
step = (max - min).to_f / colors.size.to_f
curr = min

colors = colors.map do |c|
  asgn = [c, curr]

  curr += step

  asgn
end

# And we begin - assign a color to each state
#
# No BST in the stdlib :(
colored_data = joined.inject({}) do |r, (state, value)|
  # Look up the color

  # Grab the values of the first color
  curr  = colors.first.last
  color = colors.first.first

  colors.each do |(c, range_max)|
    break if curr >= value

    color = c
    curr  = range_max
  end

  r.merge(state => [state, value, color])
end

# Now that each state has a color assigned to it,
# fill it in on the map
File.open(options[:svg]) do |fh|
  doc = REXML::Document.new(fh)

  doc.elements.each("svg/path") do |p|
    state = p.attributes["id"]

    if colored_data[state]
      color = colored_data[state].last

      p.attributes["style"] = p.attributes["style"].sub(/fill:.+?;/, "fill:##{color};")
    end
  end

  File.open(options[:out], 'w+') do |o|
    o.puts doc.to_s
  end
end
